module riscv32 #(
	parameter [31:0] MASKED_IRQ = 32'h 0000_0000,
	parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff,
	parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
	parameter [31:0] PROGADDR_IRQ = 32'h 0000_0004,
	parameter [31:0] STACKADDR = 32'h ffff_ffff
) (
	input clk, resetn,
	output trap,

	output         mem_valid,
	output         mem_instr,
	input          mem_ready,

	output  [31:0] mem_addr,
	output  [31:0] mem_wdata,
	output  [ 3:0] mem_wstrb,
	input   [31:0] mem_rdata,

	// IRQ Interface
	input   [31:0] irq,
	output  [31:0] eoi,

    output  [31:0] PC,
	// Trace Interface
	output         trace_valid,
	output  [35:0] trace_data,
    output cpu_reset,
	output uart_tx,
	input uart_rx

);

wire reg_we_u1;
wire reg_we_u2;
wire irq_state;

uart_debug #(
	.CLK_FREQ	(27000000),
	.UART_BPS	(115200)
) uart_debug_u1(
    .clk(clk),
    .resetn(resetn),
    .reset_out(cpu_reset),

    .uart_rx(uart_rx),
    .uart_tx(uart_tx),

    .reg_addr(),
    .data(),
    .reg_we()
);
reg mem_instr_r;
wire mem_instr_pos;
always@(posedge clk) mem_instr_r <= mem_instr;
assign mem_instr_pos = mem_instr&(~mem_instr_r);
wire time_irq;
assign time_irq = (timer_cnt == timer_commpare);
reg [31:0] timer_commpare;
reg [31:0] timer_cnt;
always@(posedge clk or negedge resetn)begin
    if(!resetn)begin
        timer_cnt <= 32'd0;
    end
    else begin
        if(mem_instr_pos)begin
            if(timer_cnt <= timer_commpare)begin
                timer_cnt <= timer_cnt + 1'b1;
            end
            else begin
                timer_cnt <= 32'd0;
            end
        end
        else begin
            timer_cnt <= timer_cnt;
        end
    end
end
wire pcpi_valid;
wire [31:0] pcpi_insn;
wire [31:0] pcpi_rs1;
wire [31:0] pcpi_rs2;
reg  [31:0] pcpi_rd;
reg         pcpi_reg_we;
reg pcpi_error;
reg  pcpi_ready;
reg [3:0] pcpi_cnt;

always@(posedge clk or negedge cpu_reset) begin
    if(!cpu_reset)begin
        pcpi_ready <= 1'b0;
        pcpi_error <= 1'b0;
        pcpi_cnt <= 4'h0;
        pcpi_reg_we <= 1'b0;
        timer_commpare <= 32'hffffffff;
    end
    else begin
        // if(!pcpi_valid)begin
        //     pcpi_ready <= 1'b0;
        //     pcpi_error <= 1'b0;
        //     pcpi_cnt <= 4'h0;
        //     pcpi_reg_we <= 1'b0;
        // end
        // else begin
        //     // case(pcpi_insn[6:0])
        //     //     7'h77:begin
        //     //         case(pcpi_insn[31:25])
        //     //             7'h0:begin
        //     //                 case(pcpi_cnt)
        //     //                     4'h0:begin
        //     //                         pcpi_rd <= timer_commpare;
        //     //                         pcpi_cnt <= 4'h1;
        //     //                     end
        //     //                     4'h1:begin
        //     //                         pcpi_cnt <= 4'h2;
        //     //                     end
        //     //                     4'h2:begin
        //     //                         pcpi_reg_we <= 1'b1;
        //     //                         pcpi_ready <= 1'b1;
        //     //                         pcpi_cnt <= pcpi_cnt;
        //     //                     end
        //     //                 endcase
        //     //             end
        //     //             7'h1:begin
        //     //                 case(pcpi_cnt)
        //     //                     4'h0:begin
        //     //                         timer_commpare <= pcpi_rs1;
        //     //                         pcpi_cnt <= 4'h1;
        //     //                     end
        //     //                     4'h1:begin
        //     //                         pcpi_cnt <= 4'h2;
        //     //                     end
        //     //                     4'h2:begin
        //     //                         pcpi_ready <= 1'b1;
        //     //                         pcpi_cnt <= pcpi_cnt;
        //     //                     end
        //     //                 endcase
        //     //             end
                        
        //     //         endcase
                    
                    
        //     //     end
        //     //     default: begin
        //     //         pcpi_error <= 1'b1;
        //     //         pcpi_ready <= 1'b1;
        //     //     end
        //     // endcase
        //     pcpi_ready <= 1'b1;
        // end
        pcpi_ready <= 1'b1;
    end
end
riscv32_alu #(
	.MASKED_IRQ(MASKED_IRQ),
	.LATCHED_IRQ(LATCHED_IRQ),
	.PROGADDR_RESET(PROGADDR_RESET),
	.PROGADDR_IRQ(PROGADDR_IRQ),
	.STACKADDR(STACKADDR)
) riscv32_alu_u1(
	.clk(clk),
    .resetn(cpu_reset),
	.trap(trap),

	.mem_valid(mem_valid),
	.mem_instr(mem_instr),
	.mem_ready(mem_ready),

	.mem_addr(mem_addr),
	.mem_wdata(mem_wdata),
	.mem_wstrb(mem_wstrb),
	.mem_rdata(mem_rdata),
	// IRQ Interface
	.irq({3'd0,time_irq,irq[27:0]}),
	.irq_state(),

    // Pico Co-Processor Interface (PCPI)
	.pcpi_valid(pcpi_valid),
	.pcpi_insn(pcpi_insn),
    .pcpi_rs1(pcpi_rs1),
    .pcpi_rs2(pcpi_rs2),
    .pcpi_rd(pcpi_rd),
    .pcpi_reg_we(pcpi_reg_we),
	.pcpi_error(pcpi_error),
	.pcpi_ready(pcpi_ready),
    .PC(PC),
	// Trace Interface
	.halt(1'b0),
	.mret(),
	.mcause(),
    .mie()

);
endmodule
